package top.xana.acg.common.base.adp

import android.view.LayoutInflater
import android.view.View
import android.view.View.OnLongClickListener
import android.view.ViewGroup
import androidx.annotation.IdRes
import androidx.annotation.LayoutRes
import androidx.databinding.DataBindingUtil
import androidx.databinding.ViewDataBinding
import androidx.recyclerview.widget.RecyclerView
import androidx.viewbinding.ViewBinding
import top.xana.acg.common.R
import java.util.*

abstract class RecyclerAdapter<Data>(
    protected val mDataList: MutableList<Data>,
    /**
     * 设置适配器的监听
     *
     * @param adapterListener AdapterListener
     */
    var listener: OnItemListener<Data>?
) : RecyclerView.Adapter<RecyclerAdapter.ViewHolder<Data>>(), View.OnClickListener,
    OnLongClickListener, AdapterCallback<Data> {

    /**
     * 构造函数模块
     */
    @JvmOverloads
    constructor(listener: OnItemListener<Data>? = null) : this(ArrayList<Data>(), listener) {
    }

    /**
     * 复写默认的布局类型返回
     *
     * @param position 坐标
     * @return 类型，其实复写后返回的都是XML文件的ID
     */
    override fun getItemViewType(position: Int): Int {
        return getItemViewType(position, mDataList[position])
    }

    /**
     * 得到布局的类型
     *
     * @param position 坐标
     * @param data     当前的数据
     * @return XML文件的ID，用于创建ViewHolder
     */
    @LayoutRes
    protected abstract fun getItemViewType(position: Int, data: Data): Int

    /**
     * 创建一个ViewHolder
     *
     * @param parent   RecyclerView
     * @param viewType 界面的类型,约定为XML布局的Id
     * @return ViewHolder
     */
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder<Data> {
        // 得到LayoutInflater用于把XML初始化为View
        val inflater = LayoutInflater.from(parent.context)
//        // 把XML id为viewType的文件初始化为一个root View
        val root = inflater.inflate(getViewType(viewType), parent, false)
//        val binding = DataBindingUtil.inflate<ViewDataBinding>(inflater, getViewType(viewType), parent, false)
        // 通过子类必须实现的方法，得到一个ViewHolder
        val holder = onCreateViewHolder(root, viewType)


        // 设置View的Tag为ViewHolder，进行双向绑定
        root.setTag(R.id.tag_recycler_holder, holder)
        // 设置事件点击
        root.setOnClickListener(this)
        root.setOnLongClickListener(this)

        // 绑定callback
        holder.callback = this
        return holder
    }

    fun getViewType(viewType: Int): Int {
        return viewType
    }

    /**
     * 得到一个新的ViewHolder
     *
     * @param view     根布局
     * @param viewType 布局类型，其实就是XML的ID
     * @return ViewHolder
     */
    protected open fun onCreateViewHolder(view: View, viewType: Int) = object : ViewHolder<Data>(view){
        override fun onBind(data: Data) {

        }
    }

    /**
     * 绑定数据到一个Holder上
     *
     * @param holder   ViewHolder
     * @param position 坐标
     */
    override fun onBindViewHolder(holder: ViewHolder<Data>, position: Int) {
        // 得到需要绑定的数据
        val data = mDataList[position]
        // 触发Holder的绑定方法
        holder.bind(data)
    }

    /**
     * 得到当前集合的数据量
     */
    override fun getItemCount(): Int {
        return mDataList.size
    }

    /**
     * 得到数据集
     * @return
     */
    val itemList: List<Data>
        get() = mDataList

    /**
     * 插入一条数据并通知插入
     *
     * @param data Data
     */
    fun add(data: Data) {
        mDataList.add(data)
        notifyItemInserted(mDataList.size - 1)
    }

    fun add(data: Data, i: Int) {
        mDataList.add(i, data)
        notifyItemInserted(i)
    }

    /**
     * 插入一堆数据，并通知这段集合更新
     *
     * @param dataList Data
     */
    fun add(vararg dataList: Data) {
        if (dataList != null && dataList.size > 0) {
            val startPos = mDataList.size
            Collections.addAll(mDataList, *dataList)
            notifyItemRangeInserted(startPos, dataList.size)
        }
    }

    /**
     * 插入一堆数据，并通知这段集合更新
     *
     * @param dataList Data
     */
    fun addAll(dataList: Collection<Data>?) {
        if (dataList != null && dataList.size > 0) {
            val startPos = mDataList.size
            mDataList.addAll(dataList)
            notifyItemRangeInserted(startPos, dataList.size)
        }
    }

    /**
     * 删除操作
     */
    fun clear() {
        mDataList.clear()
        notifyDataSetChanged()
    }

    /**
     * 替换
     */
    fun replace(i: Int, data: Data) {
        if (i >= mDataList.size) {
            add(data)
            return
        }
        if (data === mDataList[i]) return
        mDataList.removeAt(i)
        mDataList.add(i, data)
        notifyItemChanged(i)
    }

    /**
     * 替换为一个新的集合，其中包括了清空
     *
     * @param dataList 一个新的集合
     */
    fun replace(dataList: Collection<Data>?) {
        mDataList.clear()
        if (dataList == null || dataList.size == 0) return
        mDataList.addAll(dataList)
        notifyDataSetChanged()
    }

    override fun update(data: Data, holder: ViewHolder<Data>) {
        // 得到当前ViewHolder的坐标
        val pos = holder.adapterPosition
        if (pos >= 0) {
            // 进行数据的移除与更新
            mDataList.removeAt(pos)
            mDataList.add(pos, data)
            // 通知这个坐标下的数据有更新
            notifyItemChanged(pos)
        }
    }

    override fun onClick(v: View) {
        val viewHolder = v.getTag(R.id.tag_recycler_holder) as ViewHolder<Data>
        if (listener != null) {
            // 得到ViewHolder当前对应的适配器中的坐标
            val pos = viewHolder.adapterPosition
            // 回掉方法
            listener?.onItemClick(viewHolder, mDataList[pos])
        }
    }

    override fun onLongClick(v: View): Boolean {
        val viewHolder = v.getTag(R.id.tag_recycler_holder) as ViewHolder<Data>
        if (listener != null) {
            // 得到ViewHolder当前对应的适配器中的坐标
            val pos = viewHolder.adapterPosition
            // 回掉方法
            listener?.onItemLongClick(viewHolder, mDataList[pos])
            return true
        }
        return false
    }

    /**
     * 我们的自定义监听器
     *
     * @param <Data> 范型
    </Data> */
    interface OnItemListener<Data> {
        // 当Cell点击的时候触发
        fun onItemClick(holder: ViewHolder<Data>, data: Data)

        // 当Cell长按时触发
        fun onItemLongClick(holder: ViewHolder<Data>, data: Data)
    }

    /**
     * 自定义的ViewHolder
     *
     * @param <Data> 范型类型
    </Data> */
    abstract class ViewHolder<Data>(view: View) : RecyclerView.ViewHolder(view){
        var callback: AdapterCallback<Data>? = null
        protected var mData: Data? = null

        /**
         * 用于绑定数据的触发
         *
         * @param data 绑定的数据
         */
        fun bind(data: Data) {
            mData = data
            onBind(data)
        }

        fun<T : View> getView(@IdRes id: Int) = itemView.findViewById<T>(id)

        /**
         * 当触发绑定数据的时候，的回掉；必须复写
         *
         * @param data 绑定的数据
         */
        protected abstract fun onBind(data: Data)

        /**
         * Holder自己对自己对应的Data进行更新操作
         *
         * @param data Data数据
         */
        fun updateData(data: Data) {
            if (callback != null) {
                callback?.update(data, this)
            }
        }
    }

    /**
     * 对回调接口做一次实现AdapterListener
     *
     * @param <Data>
    </Data> */
     abstract class OnItemListenerImpl<Data> : OnItemListener<Data> {
        override fun onItemClick(holder: ViewHolder<Data>, data: Data) {}
        override fun onItemLongClick(holder: ViewHolder<Data>, data: Data) {}
    }

}